package com.yhc.server.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yhc.common.util.JacksonUtil;
import com.yhc.common.util.ServletUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;

import java.util.Enumeration;


/**
 * 独立的日志打印切面
 */
@Slf4j
@Configuration
@Aspect
public class WebLogAop {

    private static final ObjectMapper logMapper = new ObjectMapper();

    /**
     * 以 controller 包下定义的所有请求为切入点
     */
    @Pointcut("execution(public * com.yhc.server.controller..*.*(..))")
    public void webLog() {
    }

    /**
     * 在切点之前织入
     *
     * @param joinPoint
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        // 开始打印请求日志
        HttpServletRequest request = ServletUtil.getRequest();

        // 打印请求相关参数
        log.info("### <<<------------------------- Log Start ------------------------->>>");
        // 打印请求 url
        log.info("### URL            : {}", request.getRequestURL().toString());
        // 打印 Http method
        log.info("### HTTP Method    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("### Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 打印请求的 IP
        log.info("### IP             : {}", request.getRemoteAddr());
        // 打印请求入参
        log.info("### Request Args   : {}", JacksonUtil.marshallToString(joinPoint.getArgs()));
        log.info("### Request Params   : ");
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            log.info("###    name:{}---value:{}", name, request.getParameter(name));
        }
    }

    /**
     * 在切点之后织入
     */
//    @After("webLog()")
//    public void doAfter() {
//        log.info("### <<<------------------------- Log End ------------------------->>>");
//    }

    /**
     * 环绕
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();

        // 勿修改result对象，可能会导致请求重定向
        String resultStr;
        try {
            resultStr = logMapper.writeValueAsString(result);
        } catch (Exception e) {
            // 兼容返回为URL字符串
            resultStr = result.toString();
        }
        // 打印出参
        HttpServletRequest request = ServletUtil.getRequest();
        log.info("### HTTP Url:{}, Request Args: {}, Response Args: {}", request.getRequestURI(), JacksonUtil.marshallToString(proceedingJoinPoint.getArgs()), resultStr);
        log.info("### <<<------------------------- Log End ------------------------->>>");
        return result;
    }
}
